package com.hippo.client.websocket;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hippo.core.pojo.entity.SysNotice;
import com.hippo.core.pojo.vo.result.BaseResult;
import com.hippo.database.mapper.SysNoticeMapper;
import jakarta.websocket.*;
import jakarta.websocket.server.ServerEndpoint;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;
import java.net.UnknownHostException;
import java.net.http.HttpRequest;
import java.time.LocalDateTime;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;


/**
 * @ClassName ChatEndPoint
 * @Description TODO websocket实现实时通告
 * @Author tangxl
 * @create 2023-04-21 10:40
 **/
@ServerEndpoint("/webSocket/notices")
@Component
@Slf4j
@EnableScheduling // 开启定时任务
public class WebsocketNotice{
    /**
     * 静态变量，用来记录当前在线连接数，应该把它设计成线程安全的。
     */
    private static AtomicInteger onlineNum = new AtomicInteger();

    /**
     * 用于存放所有在线客户端
     */
    private static CopyOnWriteArraySet<WebsocketNotice> webSocketSet = new CopyOnWriteArraySet<>();

    /**
     * 会话,这里的session是websocket的session
     */
    private Session session;

    private static SysNoticeMapper sysNoticeMapper;
    private static ApplicationContext applicationContext;
    public static void setApplicationContext(ApplicationContext applicationContext){
        WebsocketNotice.applicationContext = applicationContext;
    }

    /**
     * 连接建立成功调用的方法
     */
    @OnOpen
    public void onOpen(Session session){
        // 生成唯一数字
        String uuid = StrUtil.uuid();
        // 在线人数加1
        onlineNum.incrementAndGet();
        // 添加在线客户端
        webSocketSet.add(this);
        // 会话赋值
        this.session = session;
        log.info("有新连接加入!连接总数：" + onlineNum);
        // 获取通告信息
        sysNoticeMapper = applicationContext.getBean(SysNoticeMapper.class);
        List<SysNotice> sysNoticeList = sysNoticeMapper.selectSysNoticeByCutOffTime(LocalDateTime.now());
        // 发送通知给客户端
        try {
            sendMessage(session, JSON.toJSONString(BaseResult.ok(200,"获取成功",sysNoticeList)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("websocket IO异常");
        }
    }

    /**
     * 定时发送通告信息任务1
     * 任务时间：每10秒执行一次
     */
//    @Scheduled(fixedRate = 1000 * 10) // 每10秒执行一次
//    @Scheduled(cron = "0/10 * * * * ?")
    public void configTask1(){
        // 获取通告信息
        sysNoticeMapper = applicationContext.getBean(SysNoticeMapper.class);
        List<SysNotice> sysNoticeList = sysNoticeMapper.selectSysNoticeByCutOffTime(LocalDateTime.now());
        // 发送通知给客户端
        try {
            for (WebsocketNotice websocketNotice : webSocketSet) {
                sendMessage(websocketNotice.session, JSON.toJSONString(BaseResult.ok(200,"获取成功",sysNoticeList)));
            }
            log.info("定时发送通告信息任务1成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("websocket IO异常");
        }
    }

    /**
     * 定时发送通告信息任务2
     * 请求接口获取通告信息
     * 任务时间：每30秒执行一次
     */
//    @Scheduled(fixedRate = 1000 * 30) // 每30秒执行一次
//    @Scheduled(cron = "0/30 * * * * ?")
    public void configTask2(){
        try {
            // 获取本机IP地址
            Inet4Address inet4Address = (Inet4Address) Inet4Address.getLocalHost();
            String hostAddress = inet4Address.getHostAddress();
            //调用本地接口获取通告信息
            String url = "http://"+hostAddress+":9003/notice/getNoticeList";
            String result = HttpUtil.get(url,3000);
            // 发送通知给客户端
            for (WebsocketNotice websocketNotice : webSocketSet) {
                sendMessage(websocketNotice.session, result);
            }
            log.info("定时调用本地接口获取通告信息任务2成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("获取本机IP地址失败");
        }
    }

    /**
     * 客户端发送消息
     * @param message
     */
    @OnMessage
    public  void onMessage(String message) {
        log.info("来自客户端的消息:" + message);
        // 获取通告信息
        sysNoticeMapper = applicationContext.getBean(SysNoticeMapper.class);
        List<SysNotice> sysNoticeList = sysNoticeMapper.selectSysNoticeByCutOffTime(LocalDateTime.now());
        // 发送通知给客户端
        try {
            sendMessage(session, JSON.toJSONString(BaseResult.ok(200,"获取成功",sysNoticeList)));
        } catch (Exception e) {
            e.printStackTrace();
            log.error("websocket IO异常");
        }
    }

    /**
     * 关闭连接
     */
    @OnClose
    public void onClose(){
        // 在线人数减1
        onlineNum.decrementAndGet();
        // 移除在线客户端
        webSocketSet.remove(this);
    }

    /**
     * 发生错误
     * @param session
     * @param error
     */
    @OnError
    public void onError(Session session,Throwable error){
        log.error("发生错误");
        error.printStackTrace();
    }

    /**
     * 指定用户发送消息
     * @param session
     * @param message
     * @throws Exception
     */
    public void sendMessage(Session session, String message) throws Exception {
        if(session != null){
            synchronized (session) {
                System.out.println("发送数据：" + message);
                session.getBasicRemote().sendText(message);
            }
        }
    }




}
